package lambda;

import org.junit.Test;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 * 一、lambda 表达式的基础语法：Java 8 中引入了一个新的操作符 "->" 该操作符称为箭头操作符或者 Lambda 操作符
 *     箭头操作符将 Lambda 表达式拆分成两部分：
 *     左侧：Lambda 表达式的参数列表
 *     右侧：Lambda 表达式中所需执行的功能，即 Lambda 体
 *
 * 语法格式一：无参数，无返回值
 *      () -> System.out.println("Hello lambda");
 *
 * 语法格式二：有一个参数，且无返回值
 *      (x) -> System.out.println(x);
 *
 * 语法格式三：有一个参数（小括号可以省略不写），且无返回值
 *      x -> System.out.println(x);
 *
 * 语法格式四：有两个以上的参数，有返回值，并且lambda体中有多条语句
 *      (x, y) -> {
 *
 *      }
 *      Comparator<Integer> com = (x,y) -> {
 *             System.out.println("函数式接口");
 *             // (x < y) ? -1 : ((x == y) ? 0 : 1);
 *             int result = Integer.compare(x,y);
 *             System.out.println(result);
 *             return result;
 *         };
 *
 * 语法格式五：有两个以上的参数，有返回值，并且lambda体中只有一条语句(return 和 {} 都可以省略不写)
 *      Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
 *
 * 语法格式六：Lambda 表达式的参数列表的数据类型可以省略不写，因为JVM编译器通过上下文推断出，数据类型。即 "类型推断"
 *      Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x,y);
 *
 * 二、Lambda 表达式需要函数式接口的支持
 *      函数式接口：接口中只有一个抽象函数的接口，称之为函数式接口。可以使用@FunctionalInterface 注解修饰一下
 *                可检查是否是函数式接口
 */
public class TestLambda01 {

    @Test
    public void Test1() {
        int num = 1; // 在jdk 1.7 之前，此变量想在局部内部类中使用，必须是final的
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello World1!" + num);
            }
        };
        r.run();
        System.out.println("------------------------");
        // 语法格式一：无参数，无返回值的写法
        Runnable r1 = () -> System.out.println("Hello Lambda");
        r1.run();
    }

    @Test
    public void Test2() {

        // 语法格式二：有一个参数，且无返回值的写法
        Consumer<String> con = (a) -> System.out.println(a);
        con.accept("今天天气不错");

        // 语法格式三：若lambda表达式只有一个参数，小括号可以省略不写 无返回值。
        Consumer<String> con1 = x -> System.out.println(x);
        con1.accept("今天是个好日子");
    }

    @Test
    public void Test3() {

        // 语法格式四：有两个及以上的参数，有返回值，且lambda体中有多条语句（必须使用 “{}”）
        Comparator<Integer> com = (x,y) -> {
            System.out.println("函数式接口");
            // (x < y) ? -1 : ((x == y) ? 0 : 1);
            int result = Integer.compare(x,y);
            System.out.println(result);
            return result;
        };
        com.compare(6,4);
    }

    @Test
    public void Test4() {

        // 语法格式五：有两个及以上的参数，有返回值，且lambda体中有一条语句（return 和 {} 都可以省略不写）
        Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
        System.out.println("比较的结果是:" + com.compare(6,4));
    }

    // 需求：对一个数进行运算
    @Test
    public void Test6() {
        // 这样就可以不用写两套了
        System.out.println(operation(10, x -> x + 100));
        System.out.println(operation(10, x -> x * 100));
    }

    public Integer operation(Integer x, MyFun myFun) {
        return myFun.getValue(x);
    }
}
